﻿using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Reactive.Concurrency;
using System.Reactive.Joins;

namespace System.Reactive.Linq
{
	public static partial class Observable
	{
		public static TSource Wait<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			return default(TSource);
		}

		public static IObservable<TResult> When<TResult>(params Plan<TResult>[] plans)
		{
			Contract.Requires(plans != null, null, "plans != null");
			//Contract.Requires(Contract.ForAll(plans, plan => plan != null), null, "Contract.ForAll(plans, plan => plan != null)");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> When<TResult>(this IEnumerable<Plan<TResult>> plans)
		{
			Contract.Requires(plans != null, null, "plans != null");
			//Contract.Requires(Contract.ForAll(plans, plan => plan != null), null, "Contract.ForAll(plans, plan => plan != null)");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TSource> Where<TSource>(this IObservable<TSource> source, Func<TSource, bool> predicate)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(predicate != null, null, "predicate != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Where<TSource>(this IObservable<TSource> source, Func<TSource, int, bool> predicate)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(predicate != null, null, "predicate != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> While<TSource>(Func<bool> condition, IObservable<TSource> source)
		{
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource, TWindowClosing>(this IObservable<TSource> source, Func<IObservable<TWindowClosing>> windowClosingSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(windowClosingSelector != null, null, "windowClosingSelector != null");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource>(this IObservable<TSource> source, int count)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(count > 0, null, "count > 0");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource>(this IObservable<TSource> source, TimeSpan timeSpan)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(timeSpan >= TimeSpan.Zero, null, "timeSpan >= TimeSpan.Zero");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource>(this IObservable<TSource> source, int count, int skip)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(count > 0, null, "count > 0");
			Contract.Requires(skip > 0, null, "skip > 0");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource, TWindowOpening, TWindowClosing>(this IObservable<TSource> source, IObservable<TWindowOpening> windowOpenings, Func<TWindowOpening, IObservable<TWindowClosing>> windowClosingSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(windowOpenings != null, null, "windowOpenings != null");
			Contract.Requires(windowClosingSelector != null, null, "windowClosingSelector != null");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource>(this IObservable<TSource> source, TimeSpan timeSpan, int count)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(timeSpan >= TimeSpan.Zero, null, "timeSpan >= TimeSpan.Zero");
			Contract.Requires(count > 0, null, "count > 0");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource>(this IObservable<TSource> source, TimeSpan timeSpan, IScheduler scheduler)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(timeSpan >= TimeSpan.Zero, null, "timeSpan >= TimeSpan.Zero");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource>(this IObservable<TSource> source, TimeSpan timeSpan, TimeSpan timeShift)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(timeSpan >= TimeSpan.Zero, null, "timeSpan >= TimeSpan.Zero");
			Contract.Requires(timeShift >= TimeSpan.Zero, null, "timeShift >= TimeSpan.Zero");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource>(this IObservable<TSource> source, TimeSpan timeSpan, int count, IScheduler scheduler)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(timeSpan >= TimeSpan.Zero, null, "timeSpan >= TimeSpan.Zero");
			Contract.Requires(count > 0, null, "count > 0");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}

		public static IObservable<IObservable<TSource>> Window<TSource>(this IObservable<TSource> source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(timeSpan >= TimeSpan.Zero, null, "timeSpan >= TimeSpan.Zero");
			Contract.Requires(timeShift >= TimeSpan.Zero, null, "timeShift >= TimeSpan.Zero");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<IObservable<TSource>>>() != null, null, "Contract.Result<IObservable<IObservable<TSource>>>() != null");
			return null;
		}
	}
}